/**  
 * <p>Title: ModifyAnnotaionFactory.java</p>  
 * <p>Description: </p>  
 * <p>Copyright: Copyright (c) 2017</p>  
 * <p>Company: http://www.richfit.com/</p>  
 * @author hushouquan
 * @date 2020年3月3日  
 * @version 1.0  
 */
package com.rf.richfitwheel.admin.annotation;

import org.springframework.util.ReflectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
 * <p>
 * Title: ModifyAnnotaionFactory
 * </p>
 * <p>
 * Description:
 * </p>
 * 
 * @author hushouquan
 * @date 2020年3月3日
 */
public class ModifyAnnotaionFactory {
	private static ModifyAnnotaionFactory instance = null;

	public static ModifyAnnotaionFactory newInstance() {

		if (instance == null) {
			synchronized (ModifyAnnotaionFactory.class) {
				if (instance == null) {
					instance = new ModifyAnnotaionFactory();
				}
			}
		}

		return instance;
	}

	private ModifyAnnotaionFactory() {
	}

	/**
	 *
	 * @param className
	 *            当前类名.class
	 * @param annotationName
	 *            需要修改的注解class
	 * @param methodName
	 *            需要修改的方法名
	 * @param modifyField
	 *            注解中需要修改的属性名
	 * @param paramName
	 *            注解中修改的属性值
	 * @param paramTypes
	 *            不定参数----语法糖
	 */
	public Annotation ModifyAnnotation(Class className, Class annotationName, String methodName, String modifyField,
			String paramName, Class<?>... paramTypes) {
		try {
			// 反射获取Method：methodName方法、paramTypes不定参数（“语法糖”）-----method
			Method method = className.getDeclaredMethod(methodName, paramTypes);
			// 反射当前方法的注解---annotation
			Annotation annotation = method.getAnnotation(annotationName);
			// 获取该注解的调用处理器---invocationHandler
			InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
			// 反射获取注解的属性
			Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
			// 暴力破解
			// 结算代码问题整改
			ReflectionUtils.makeAccessible(memberValues);
			// 获取所有的注解属性--map集合
			Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler);
			// 覆盖原有属性值
			values.put(modifyField, paramName);
			return annotation;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 *
	 * @param classAllPath
	 *            当前类的全路径名
	 * @param annotationName
	 *            需要修改的注解class
	 * @param methodName
	 *            需要修改的方法名
	 * @param modifyField
	 *            注解中需要修改的属性名
	 * @param paramName
	 *            注解中修改的属性值
	 * @return
	 */
	public boolean ModifyAnnotation(String classAllPath, Class annotationName, String methodName, String modifyField,
			String paramName) {
		try {
			Class<?> aClass = Class.forName(classAllPath);
			Method method = aClass.getDeclaredMethod(methodName);
			Annotation annotation = method.getAnnotation(annotationName);
			InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
			Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
			// 结算代码问题整改
			ReflectionUtils.makeAccessible(memberValues);
			Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler);

			Object o1 = values.get(modifyField);
			values.put(modifyField, paramName);
			Object o2 = values.get(modifyField);
//			System.out.println();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 获取当前注解
	 * @param className         当前类名
	 * @param annotationName    注解名
	 * @param name              方法名、类名、属性名之一
	 * @param type              注解类型
	 * @return
	 * @throws Exception
	 */
	public Annotation getAnnotation(Class className,Class annotationName,String name,Integer type) throws Exception {
		switch (type){
		case 1:
			Method method = className.getDeclaredMethod(name);
			return method.getAnnotation(annotationName);
		case 2:
//			System.out.println("2");
			return null;
		case 3:
//			System.out.println("3");
			return null;
		}
		return null;
	}
}
